package me.shiqiang.im.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.tst.common.exception.MicroServiceException;
import com.tst.common.exception.ServiceException;
import com.tst.common.pages.Pages;
import com.tst.common.returnobj.ReturnObjCode;
import com.tst.common.utils.DateUtils;
import com.tst.common.utils.JSONUtils;
import me.shiqiang.im.dao.*;
import me.shiqiang.im.domain.*;
import me.shiqiang.im.domain.DomainEnums;
import me.shiqiang.im.microservice.AchievementClient;
import me.shiqiang.im.microservice.DistributorMicroService;
import me.shiqiang.im.microservice.UserClient;
import me.shiqiang.im.microservice.UserQueryMicroService;
import me.shiqiang.im.microservice.returnobj.*;
import me.shiqiang.im.redis.RedisKey;
import me.shiqiang.im.vo.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * @author cuishiqiang
 * @date 2017/12/8 下午4:00
 */
@Service
@CacheConfig(cacheManager = "UserCacheManager", cacheNames = {"userCache"})
public class UserService {

    @Autowired
    UserDao userDao;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    UserFriendsDao userFriendsDao;

    @Autowired
    UseAuthDao useAuthDao;

    @Autowired
    ChatSwitchDao chatSwitchDao;

    @Autowired
    UserFriendRequestsDao userFriendRequestsDao;

    @Autowired
    StringRedisTemplate stringRedisTemplate;


//    @Autowired
//    UserQueryMicroService userQueryMicroService;
//
//    @Autowired
//    DistributorMicroService distributorMicroService;

    @Autowired
    AchievementClient achievementClient;

//    @Autowired
//    UserClient userClient;


//    @Cacheable(key = "'userInfoCache.'+#id")
////    public String get(Long id) throws JsonProcessingException {
//////        logger.info("用户查询微服务服务,id:{}", id);
////        UserInfoReturnObj returnObj = userQueryMicroService.findById(id);
////        if (!ReturnObjCode.SUCCESS.getCode().equals(returnObj.getCode())) {
////            logger.warn("用户查询微服务服务返回失败,response:{}", returnObj.toString());
////            throw new MicroServiceException(returnObj.getMsg());
////        }
////        return JSONUtils.toJSON(returnObj.getRes());
////    }

    @Cacheable(key = "'userInfoCache.'+#id")
    public User get(Long id) {
        return userDao.findOne(id);
    }

    public List<FriendRequestCacheVo> getFriendRequestList(Long userId) throws IOException {
        List list = new ArrayList();
        Set userIds = redisTemplate.opsForHash().keys(DomainEnums.FRIEND_REQUEST + String.valueOf(userId));
        FriendRequestCacheVo cacheVo;
        for(Object friendId : userIds){
            cacheVo = new FriendRequestCacheVo();
            cacheVo.setId(Long.valueOf(String.valueOf(friendId)));
            String cache = (String) redisTemplate.opsForHash().get(DomainEnums.FRIEND_REQUEST + String.valueOf(userId), String.valueOf(friendId));
            FriendRequestDetailVo detailVo = (FriendRequestDetailVo) JSONUtils.convert(cache, FriendRequestDetailVo.class);

            cacheVo.setDetailVo(detailVo);
            list.add(cacheVo);
        }
        return list;
    }

    public void agreeFriendRequest(AgreeFriendRequestVo vo) throws JsonProcessingException {
        String cache = (String) redisTemplate.opsForHash().get(DomainEnums.FRIEND_REQUEST + String.valueOf(vo.getUserId()), String.valueOf(vo.getFriendId()));
        FriendRequestDetailVo detailVo = null;
        try {
            detailVo = (FriendRequestDetailVo) JSONUtils.convert(cache, FriendRequestDetailVo.class);
        } catch (IOException e) {
            logger.info("redisCache转换VO异常");
        }
        if (detailVo == null) {
            logger.warn("未找到该好友请求,targetUserId{},requestUserId", vo.getUserId(), vo.getFriendId());
            throw new ServiceException("未找到该好友请求");
        }

//        UserInfoReturnObj returnObj = userQueryMicroService.findById(vo.getUserId());
//        if (!ReturnObjCode.SUCCESS.getCode().equals(returnObj.getCode())) {
//            logger.warn("用户查询微服务服务返回失败,response:{}", returnObj.toString());
//            throw new MicroServiceException(returnObj.getMsg());
//        }

        detailVo.setStatus(1);

//        addFriend(vo, vo.getFriendId());

        addFriend(vo.getUserId(),vo.getFriendId());
        addFriend(vo.getFriendId(),vo.getUserId());

        redisTemplate.opsForHash().put(DomainEnums.FRIEND_REQUEST + String.valueOf(vo.getUserId()), String.valueOf(vo.getFriendId()), JSONUtils.toJSON(detailVo));

    }

    public void newFriendRequest(FriendRequestVo vo) throws JsonProcessingException {
        String cache = (String) redisTemplate.opsForHash().get(DomainEnums.FRIEND_REQUEST + String.valueOf(vo.getTargetUserId()), String.valueOf(vo.getRequestUserId())); //更新前先查到记录

        FriendRequestDetailVo  detailVo = null;

        User user = userDao.findOne(vo.getRequestUserId()); // 用户自己发起好友请求，一般情况下不会查询不到，如果出现此种情况，让它报错，快速定位问题

        if (StringUtils.isBlank(cache)) {
            detailVo = new FriendRequestDetailVo();
            detailVo.setRequestMsg(vo.getRequestMsg());
            detailVo.setStatus(0);
            detailVo.setName(user.getName());
            detailVo.setAvatar(user.getAvatar());
            redisTemplate.opsForHash().put(DomainEnums.FRIEND_REQUEST + String.valueOf(vo.getTargetUserId()), String.valueOf(vo.getRequestUserId()), JSONUtils.toJSON(detailVo));
        } else {
            try {
                detailVo = (FriendRequestDetailVo) JSONUtils.convert(cache, FriendRequestDetailVo.class);
            } catch (IOException e) {
                logger.info("redisCache转换VO异常");
            }
            detailVo.setRequestMsg(vo.getRequestMsg());
            redisTemplate.opsForHash().put(DomainEnums.FRIEND_REQUEST + String.valueOf(vo.getTargetUserId()), String.valueOf(vo.getRequestUserId()), JSONUtils.toJSON(detailVo));
        }
    }

    public Long save(User user) {
        User userInDb = userDao.findByPhone(user.getPhone());
        if (userInDb != null) {
            throw new ServiceException("该手机号已注册");
        }

        if (user.getUserId() == null) {
//            int year = LocalDate.now().getYear();
            Long userId = stringRedisTemplate.opsForValue().increment(RedisKey.USER_ID, 1);
            user.setUserId(userId);
        }
        userDao.save(user);
        return user.getUserId();
    }

    public Long register(String phone,String pwd) {
        User user = new User();
        user.setName(phone);
        user.setPhone(phone);
        user.setPwd(pwd);
        return save(user);
    }

    public User get(String phone) {
        return userDao.findByPhone(phone);
    }

    public void addFriend(AgreeFriendRequestVo vo, UserInfoVo selfVo) {
        UserFriends self = userFriendsDao.findOne(vo.getUserId());
        if (self == null) {
            self = new UserFriends();
            self.setUserId(vo.getUserId());
        }
        UserFriends friend = userFriendsDao.findOne(vo.getFriendId());
        if (friend == null) {
            friend = new UserFriends();
            friend.setUserId(vo.getFriendId());
        }

        Friend selfFriend = new Friend();
        selfFriend.setUserId(vo.getFriendId());
        selfFriend.setName(vo.getName());
        selfFriend.setAvatar(vo.getAvatar());
        self.getFriends().put(vo.getFriendId(), selfFriend);
        userFriendsDao.save(self);

        Friend friendsFriend = new Friend();
        friendsFriend.setUserId(vo.getUserId());
        friendsFriend.setName(selfVo.getNickName());
        friendsFriend.setAvatar(selfVo.getAvatar());
        friend.getFriends().put(vo.getUserId(), friendsFriend);
        userFriendsDao.save(friend);
    }



    public UserFriends getUserFriends(Long userId) {
        return userFriendsDao.findOne(userId);
    }

    public void deleteFriend(Long userId, Long friendId) {
        UserFriends userFriends = userFriendsDao.findOne(userId);
        userFriends.getFriends().remove(friendId);
        userFriendsDao.save(userFriends);
    }

    public Boolean useAuth(Long userId) {
        String publicity = String.valueOf(redisTemplate.opsForHash().get("chatAuth", "publicity"));
        if (publicity.equals("0")) {
            return false;
        }
        if (publicity.equals("1") ) {
            return true;
        }
        return useAuthDao.findOne(userId) != null;
    }

    public void publicity(String open) {
        redisTemplate.opsForHash().put("chatAuth", "publicity", open);
    }

    public void addFriend(Long userId, Long friendId) {
        User friendInfo = userDao.findOne(friendId);
        if (friendInfo == null) {
            throw new ServiceException(String.format("未找到该用户,uid: %s",friendId));
        }

        UserFriends one = userFriendsDao.findOne(userId);
        if (one == null) {
            one = new UserFriends();
            one.setUserId(userId);
        }
        Friend friend = new Friend();
        friend.setUserId(friendId);
        friend.setName(friendInfo.getName());
        friend.setAvatar(friendInfo.getAvatar());
        one.getFriends().put(friendId, friend);
        userFriendsDao.save(one);

        User user = userDao.findOne(userId);
        if (user == null) {
            throw new ServiceException(String.format("未找到该用户,uid: %s",userId));
        }
        UserFriends friendFriends = userFriendsDao.findOne(friendId);
        if (friendFriends == null) {
            friendFriends = new UserFriends();
            friendFriends.setUserId(friendId);
        }
        Friend newFriend = new Friend();
        newFriend.setUserId(userId);
        newFriend.setName(user.getName());
        newFriend.setAvatar(user.getAvatar());
        friendFriends.getFriends().put(userId, newFriend);
        userFriendsDao.save(one);
//    }
    }

    public void addUseAuth(Long userId) {
        UseAuth useAuth = new UseAuth();
        useAuth.setServerId(userId.toString());
        useAuthDao.save(useAuth);
    }

    @CacheEvict(key = "'cs'+#userId")
    public void chatSwitch(Long userId, int type) {
        if (type == 1) {
            ChatSwitch chatSwitch = new ChatSwitch();
            chatSwitch.setUserId(userId);
            chatSwitchDao.save(chatSwitch);
        }else {
            chatSwitchDao.delete(userId);
        }

    }

    @Cacheable(key = "'cs'+#userId")
    public boolean chatSwitch(Long userId) {
        return chatSwitchDao.exists(userId);
    }

    public void modifyPwd(Long userId, String pwd, String newPwd) {

//        User user = userDao.findByUserIdAndPwd(userId, pwd);
        User user = userDao.findOne(userId);

        if (user == null || !user.getPwd().equals(pwd)) {
            throw new ServiceException("密码错误");
        }
        user.setPwd(newPwd);
        userDao.save(user);
    }

    public void modifyInfo(Long userId, String name, String avatar, Integer gender) {
        User user = userDao.findOne(userId);

        if (user == null) {
            throw new ServiceException(String.format("未找到该用户,uid: %s",userId));
        }
        if (StringUtils.isNotBlank(name)) {
            user.setName(name);
        }
        if (StringUtils.isNotBlank(avatar)) {
            user.setAvatar(avatar);
        }
        if (gender != null && gender != 0) {
            user.setGender(gender);
        }
        userDao.save(user);
    }

    public User login(String userName, String pwd) {
        User user = userDao.findByPhoneAndPwd(userName, pwd);
        if (user == null) {
            throw new ServiceException("用户名或密码错误");
        }
        return user;
    }
}
